package com.itstyle.seckill.topic.executor;

import java.util.Date;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Auther: liuwenxiang
 * @Date: 2020/4/3 10:40
 * @Description:
 */
public class ScheduleTest {


    /**
     * 实现周期性调度，线程池内设置一个线程就满足
     *
     * ps:当线程池设置多个线程时，就会开启多个线程执行，多个线程执行规律跟一个线程一样，只是每次选取的执行线程不一样而已
     */
    private  static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);


    /**
     *
     *  private  static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
     *
     * 线程池开始启动：Fri Apr 03 12:37:45 CST 2020
     * begin===Fri Apr 03 12:37:48 CST 2020pool-1-thread-1
     * 执行时间0
     * end===Fri Apr 03 12:37:48 CST 2020pool-1-thread-1
     * begin===Fri Apr 03 12:37:52 CST 2020pool-1-thread-1
     * 执行时间1
     * end===Fri Apr 03 12:37:53 CST 2020pool-1-thread-1
     * begin===Fri Apr 03 12:37:56 CST 2020pool-1-thread-2
     * 执行时间6
     * java.lang.ArithmeticException: / by zero
     * 	at com.itstyle.seckill.topic.executor.ScheduleTest$Runner.run(ScheduleTest.java:161)
     * 	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
     * 	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
     * 	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
     * 	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
     * 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
     * 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
     * 	at java.lang.Thread.run(Thread.java:748)
     * begin===Fri Apr 03 12:38:02 CST 2020pool-1-thread-1
     * 执行时间2
     * end===Fri Apr 03 12:38:04 CST 2020pool-1-thread-1
     * begin===Fri Apr 03 12:38:04 CST 2020pool-1-thread-3
     * 执行时间4
     * end===Fri Apr 03 12:38:08 CST 2020pool-1-thread-3
     * begin===Fri Apr 03 12:38:08 CST 2020pool-1-thread-2
     * 执行时间4
     * end===Fri Apr 03 12:38:12 CST 2020pool-1-thread-2
     * begin===Fri Apr 03 12:38:12 CST 2020pool-1-thread-4
     * 执行时间0
     * end===Fri Apr 03 12:38:12 CST 2020pool-1-thread-4
     * begin===Fri Apr 03 12:38:16 CST 2020pool-1-thread-1
     * 执行时间4
     * end===Fri Apr 03 12:38:20 CST 2020pool-1-thread-1
     * begin===Fri Apr 03 12:38:20 CST 2020pool-1-thread-5
     * 执行时间2
     * end===Fri Apr 03 12:38:22 CST 2020pool-1-thread-5
     * @param args
     */




    public static void main(String[] args) {
        //fixedRate();

        //fixedDelay();

        scheduled();
        scheduled();
        scheduled();

        //scheduled1();
    }

    public static void scheduled(){
        scheduledExecutorService.schedule(new Runner(),10,TimeUnit.SECONDS);
        System.out.println("线程池开始启动："+new Date());
        /**
         * 线程池开始启动：Fri Apr 03 12:25:42 CST 2020
         *      ps1:线程池启动4s后，开始执行任务,任务只执行一次

     "开启三个延迟执行的线程"
         线程池开始启动：Wed Apr 08 10:36:11 CST 2020
         线程池开始启动：Wed Apr 08 10:36:11 CST 2020
         线程池开始启动：Wed Apr 08 10:36:11 CST 2020
         begin===Wed Apr 08 10:36:21 CST 2020pool-1-thread-1
         执行时间2
         begin===Wed Apr 08 10:36:21 CST 2020pool-1-thread-2
         执行时间5
         begin===Wed Apr 08 10:36:21 CST 2020pool-1-thread-3
         执行时间0
         end===Wed Apr 08 10:36:21 CST 2020pool-1-thread-3
         end===Wed Apr 08 10:36:23 CST 2020pool-1-thread-1
         end===Wed Apr 08 10:36:26 CST 2020pool-1-thread-2

         */
    }

    public static void scheduled1(){
        ScheduledFuture scheduledFuture =  scheduledExecutorService.schedule(new Caller(),4,TimeUnit.SECONDS);
        System.out.println("线程池开始启动："+new Date());
        /**
         线程池开始启动：Fri Apr 03 12:33:33 CST 2020
             ps1:线程池启动4s后，开始执行任务,任务只执行一次
         begin===Fri Apr 03 12:33:37 CST 2020pool-1-thread-1
         end===Fri Apr 03 12:33:47 CST 2020pool-1-thread-1
            ps2:阻塞式等待线程执行后，获取结果
            我是返回值:Fri Apr 03 12:33:47 CST 2020
         */
        try {
            System.out.println(scheduledFuture.get()+":"+new Date());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("执行完。。。");
    }

    public static void fixedDelay(){
        scheduledExecutorService.scheduleWithFixedDelay(new Runner(),3,4,TimeUnit.SECONDS);
        System.out.println("线程池开始启动："+new Date());

        /**
         线程池开始启动：Fri Apr 03 12:17:24 CST 2020
            ps1:线程池启动3s后，开始执行任务
         begin===Fri Apr 03 12:17:27 CST 2020pool-1-thread-1
         执行时间0
         end===Fri Apr 03 12:17:27 CST 2020pool-1-thread-1
            ps2:每个任务设置的执行时间4s，无论上一个任务执行多久，下一个任务都间隔4s再执行
         begin===Fri Apr 03 12:17:31 CST 2020pool-1-thread-1
         执行时间2
         end===Fri Apr 03 12:17:33 CST 2020pool-1-thread-1
         begin===Fri Apr 03 12:17:37 CST 2020pool-1-thread-1
         执行时间4
         java.lang.ArithmeticException: / by zero
         at com.itstyle.seckill.topic.executor.ScheduleTest$Runner.run(ScheduleTest.java:91)
         at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
         at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
         at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
         at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
         at java.lang.Thread.run(Thread.java:748)
         begin===Fri Apr 03 12:17:45 CST 2020pool-1-thread-1
         执行时间2
         end===Fri Apr 03 12:17:47 CST 2020pool-1-thread-1
         .....
         begin===Fri Apr 03 12:18:10 CST 2020pool-1-thread-1
         执行时间5
         end===Fri Apr 03 12:18:15 CST 2020pool-1-thread-1

         begin===Fri Apr 03 12:18:19 CST 2020pool-1-thread-1
         执行时间3
         end===Fri Apr 03 12:18:22 CST 2020pool-1-thread-1

         */
    }

    public static  void fixedRate(){
        scheduledExecutorService.scheduleAtFixedRate(new Runner(),3,4,TimeUnit.SECONDS);
        System.out.println("线程池开始启动："+new Date());
        /**
         线程池开始启动：Fri Apr 03 12:09:35 CST 2020
             ps1:线程池启动3s后，开始执行任务
         begin===Fri Apr 03 12:09:38 CST 2020pool-1-thread-1
         执行时间6
         end===Fri Apr 03 12:09:44 CST 2020pool-1-thread-1
            ps2:每个任务设置的执行时间4s，超过4s，后面的任务推迟，但任务之间没有间隔时间
         begin===Fri Apr 03 12:09:44 CST 2020pool-1-thread-1
         执行时间4
         end===Fri Apr 03 12:09:48 CST 2020pool-1-thread-1

         begin===Fri Apr 03 12:09:48 CST 2020pool-1-thread-1
         执行时间0
         java.lang.ArithmeticException: / by zero
         at com.itstyle.seckill.topic.executor.ScheduleTest$Runner.run(ScheduleTest.java:74)
         at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
         at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
         at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
         at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
         at java.lang.Thread.run(Thread.java:748)
            ps3:每个任务设置的执行时间4s，出现异常，当前任务停止，下一个周期调度继续
         begin===Fri Apr 03 12:09:50 CST 2020pool-1-thread-1
         执行时间2
         end===Fri Apr 03 12:09:52 CST 2020pool-1-thread-1
            ps4:每个任务设置的执行时间4s，任务执行小于4s，下一个任务到4s后在执行
         begin===Fri Apr 03 12:09:54 CST 2020pool-1-thread-1
         执行时间2
         end===Fri Apr 03 12:09:56 CST 2020pool-1-thread-1
         */
    }

    static  class Runner implements Runnable{

        private AtomicInteger atomicInteger =null;
        private Random random =null;
        public Runner(){
            atomicInteger = new AtomicInteger();
            random = new Random();
        }
        @Override
        public void run() {

            try {
                System.out.println("begin==="+new Date()+Thread.currentThread().getName());
                int randoms = random.nextInt(7);//7之内的随机数
                System.out.println("执行时间"+randoms);
                TimeUnit.SECONDS.sleep(randoms);
                if(atomicInteger.addAndGet(1)==3){
                    int i=3/0;  /** 故意抛出一个异常*/
                }
                System.out.println("end==="+new Date()+Thread.currentThread().getName());
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }




    static class Caller implements Callable{

        private AtomicInteger atomicInteger =null;
        private Random random =null;
        public Caller(){
            atomicInteger = new AtomicInteger();
            random = new Random();
        }

        @Override
        public Object call() throws Exception {
            try {
                System.out.println("begin==="+new Date()+Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(10);
                System.out.println("end==="+new Date()+Thread.currentThread().getName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "我是返回值";
        }
    }
}
